#ifndef QIGRAMMAR
#define QIGRAMMAR
#include <iostream>
#include <string>
#include <complex>
#include <fstream>
#include "../../base/TemplateParser/BO.h"


#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;



//===========================================PARSER==========================================
namespace qigrammar
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace phoenix = boost::phoenix;


	template <typename Iterator>
	struct direction_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection()>
	{
		direction_grammar() : direction_grammar::base_type(start)
		{
			using qi::lexeme;
			using ascii::char_;
			using qi::_1;
			using qi::lit;
			using qi::_val;
			using phoenix::at_c;
			start =*(char_ -'@')
						  >> '@' >> +(char_ -' ' -'\n' -'\t' -'\r' -'(' -'{' -')' -'}' -'=')
						  >> +char_;
		}
		qi::rule<Iterator, TemplateParser::BO::parsedirection()> start;
	};

	template <typename Iterator>
	struct function_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection()>
	{
		function_grammar() : function_grammar::base_type(start)
		{
			using qi::lexeme;
			using ascii::char_;
			using qi::_1;
			using qi::_val;
			using qi::lit;
			using phoenix::at_c;
			start =lexeme[+(char_-'(')[at_c<1>(_val)+=_1]>>"(">>+(char_-')')[at_c<0>(_val)+=_1]>>')'];
		}
		qi::rule<Iterator, TemplateParser::BO::parsedirection()> start;
	};




	//IF grammar===============
	template <typename Iterator>
		struct else_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type>
		{
			else_grammar () : else_grammar ::base_type(start)
			{
				using qi::lexeme;
				using ascii::char_;
				using qi::_1;
				using qi::_val;
				using qi::lit;
				using qi::eps;
				using phoenix::at_c;
				//start =+char_("else")[at_c<1>(_val)+=_1]>>"}";
				start =lexeme[+(char_ - '{' -'(')[at_c<0>(_val)+=_1]
				              >>*char_("{(")
				              >>*char_[at_c<2>(_val)+=_1]];
			}
			qi::rule<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type> start;
		};

	template <typename Iterator>
	struct equal_operation_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type>
	{
		equal_operation_grammar () : equal_operation_grammar ::base_type(start)
		{
			using qi::lexeme;
			using ascii::char_;
			using qi::_1;
			using qi::_val;
			using qi::lit;
			using phoenix::at_c;
			start =lit('=')
					>>lexeme[+(char_ - '\r' -'\n')[at_c<0>(_val)+=_1]>>*char_("\r\n")>>*char_[at_c<2>(_val)+=_1]];
		}
		qi::rule<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type> start;
	};
	template <typename Iterator>
	struct compare_operation_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type>
	{
		compare_operation_grammar  () : compare_operation_grammar  ::base_type(start)
		{
			using qi::lit;
			using ascii::char_;
			using qi::_1;
			using qi::_val;

			using phoenix::at_c;
			using qi::lexeme;


			start =	lexeme[+(char_-'!' -'=' -'<' -'>')[at_c<0>(_val)+=_1]]
			        >>+char_("!=<>") [at_c<1>(_val)+=_1]
					>>lexeme[+(char_-'!' -'=' -'<' -'>')[at_c<2>(_val)+=_1]];
		}
		qi::rule<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type> start;
	};
	template <typename Iterator>
		struct string_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type>
		{
			string_grammar  () : string_grammar  ::base_type(start)
			{
				using qi::lit;
				using ascii::char_;
				using qi::_1;
				using qi::_val;

				using phoenix::at_c;
				using qi::lexeme;



				start =lexeme['"'
						>>+(char_ -'"')[at_c<0>(_val)+=_1]
				        >>'"'];
			}
			qi::rule<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type> start;
		};
	template <typename Iterator>
	struct removespace_grammar : qi::grammar<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type>
	{
		removespace_grammar   () : removespace_grammar   ::base_type(start)
		{
			using qi::lexeme;
			using ascii::char_;
			using qi::_1;
			using qi::_val;
			using qi::lit;
			using phoenix::at_c;
			//start %=lexeme['@' >> +(char_ - ' ')];
			start =*(char_ -'"')[at_c<0>(_val)+=_1]>>lexeme[lit('"')[at_c<0>(_val)+='"']>> +(char_ -'"')[at_c<0>(_val)+=_1]>>lit('"')[at_c<0>(_val)+='"']]>>+char_[at_c<0>(_val)+=_1];
		}
		qi::rule<Iterator, TemplateParser::BO::parsedirection(), ascii::space_type> start;
	};


}

BOOST_FUSION_ADAPT_STRUCT(
	TemplateParser::BO::parsedirection,

    (std::string, out)
    (std::string, direction)
    (std::string, in)
)

#endif
